package com.chen.blue.service.system.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chen.blue.converter.system.MenuRoleConverter;
import com.chen.blue.converter.system.RoleConverter;
import com.chen.blue.converter.system.UserConverter;
import com.chen.blue.dictionary.CommonDict;
import com.chen.blue.domain.delete.system.MenuRoleDelete;
import com.chen.blue.domain.delete.system.RoleDelete;
import com.chen.blue.domain.dto.system.MenuRoleDto;
import com.chen.blue.domain.dto.system.RoleDto;
import com.chen.blue.domain.dto.system.update.MenuRoleDtoEdit;
import com.chen.blue.domain.dto.system.update.RoleDtoEdit;
import com.chen.blue.domain.model.system.RoleModel;
import com.chen.blue.domain.model.system.UsersModel;
import com.chen.blue.domain.query.system.RoleQuery;
import com.chen.blue.domain.vo.system.RoleVo;
import com.chen.blue.domain.vo.system.UserVo;
import com.chen.blue.exception.e.DtoNullException;
import com.chen.blue.exception.e.NoDeleteException;
import com.chen.blue.mapper.system.RoleMapper;
import com.chen.blue.result.DataResult;
import com.chen.blue.service.candidate.CandidateInfoService;
import com.chen.blue.service.system.IMenuRoleService;
import com.chen.blue.service.system.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.blue.utils.PageInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author CLT
 * @since 2024-04-27
 */
@Service("iRoleService")
public class IRoleServiceImpl extends ServiceImpl<RoleMapper, RoleModel> implements IRoleService {

    @Resource
    private IMenuRoleService iMenuRoleService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addRole(RoleDto roleDto) throws DtoNullException {

        if (Objects.isNull(roleDto)) {
            throw new DtoNullException("参数为空");
        }

        // 1为内置用户，2为自定义用户，默认为自定义
        roleDto.setType(2);

        RoleModel roleModel = RoleConverter.dtoToModel(roleDto);

        CandidateInfoService.setCreator(roleModel);

        boolean var1 = super.save(roleModel);
        Long roleId = var1 == true ? roleModel.getId() : null;
        List<Long> menuIds = roleDto.getMenuIds();

        boolean var2 = Objects.nonNull(menuIds) && !menuIds.isEmpty() ? iMenuRoleService.addRoleMenu(buildMenuRoleDto(roleId, menuIds)) : false;
        if (!var2) log.warn("角色未分配菜单");

        return var1;

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteRole(RoleDelete roleDelete) throws DtoNullException, NoDeleteException {

        if (Objects.isNull(roleDelete)) {
            throw new DtoNullException("参数为空");
        }

        // 内置角色不可删除，角色类型(1内置 2自定义)
        isDeleted(roleDelete);

        Map<String, Object> wrap = new HashMap<>();
        if (Objects.nonNull(roleDelete.getId())) {
            wrap.put("id", roleDelete.getId());
        }
        boolean var1 = Objects.nonNull(roleDelete.getIds()) ? super.removeByIds(roleDelete.getIds()) : super.removeByMap(wrap);

        MenuRoleDelete menuRoleDelete = new MenuRoleDelete();
        boolean var2 = iMenuRoleService.deleteRoleMenu(Objects.isNull(roleDelete.getIds()) || roleDelete.getIds().isEmpty() ? menuRoleDelete.setRoleId(roleDelete.getId()) : menuRoleDelete.setRoleIds(roleDelete.getIds()));
        if (!var2) log.warn("角色菜单删除失败");

        return var1;

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateRoleById(RoleDtoEdit roleDtoEdit) throws DtoNullException {

        if (Objects.isNull(roleDtoEdit)) {
            throw new DtoNullException("参数为空");
        }

        // 内置角色不可修改
        updatedEnabled(roleDtoEdit);

        RoleModel roleModel = RoleConverter.dtoEditToModel(roleDtoEdit);

        CandidateInfoService.setUpdater(roleModel);

        boolean var1 = super.updateById(roleModel);

        Long roleId = roleModel.getId();
        List<Long> menuIds = roleDtoEdit.getMenuIds();
        boolean var2 = Objects.nonNull(menuIds) && !menuIds.isEmpty() ? iMenuRoleService.updateRoleMenu(buildMenuRoleDtoEdit(roleId, menuIds)) : false;
        if (!var2) log.warn("角色菜单未修改");

        return var1;

    }

    @Override
    public DataResult<List<RoleVo>> queryRole(RoleQuery roleQuery) throws DtoNullException {

        if (Objects.isNull(roleQuery)) {
            throw new DtoNullException("查询条件为空");
        }

        LambdaQueryWrapper<RoleModel> wrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(roleQuery.getPageNo()) && Objects.nonNull(roleQuery.getPageSize())) {
            PageHelper.startPage(roleQuery.getPageNo(), roleQuery.getPageSize());
        }
        wrapper.orderByDesc(RoleModel::getCreateTime);

        List<RoleModel> roleModelList = super.list(wrapper);
        PageInfo<RoleModel> pageInfo = new PageInfo<>(roleModelList);
        PageHelper.clearPage();

        /**
         * 统一结果返回
         */
        DataResult<List<RoleVo>> dataResult = new DataResult<>();
        dataResult.setData(RoleConverter.modelToVoList(pageInfo.getList()));
        PageInfoUtil.setPageInfo(dataResult, pageInfo);

        return dataResult;

    }

    @Override
    public DataResult<RoleVo> queryRoleById(Long id) throws DtoNullException {

        if (Objects.isNull(id)) {
            throw new DtoNullException("ID为空");
        }

        RoleModel roleModel = super.getById(id);

        DataResult<RoleVo> dataResult = new DataResult<>();
        dataResult.setData(RoleConverter.modelToVo(roleModel));

        return dataResult;

    }


    /**
     * 判断是否可以删除
     *
     * @param roleDelete
     */
    protected void isDeleted(RoleDelete roleDelete) throws NoDeleteException, DtoNullException {

        if (Objects.isNull(roleDelete.getId()) && Objects.isNull(roleDelete.getIds()) && roleDelete.getIds().isEmpty()) {
            throw new DtoNullException("参数为空");
        }

        RoleModel roleModel = Objects.nonNull(roleDelete.getId()) ? super.getById(roleDelete.getId()) : new RoleModel();
        List<RoleModel> roleModelList = (Objects.nonNull(roleDelete.getIds()) && !roleDelete.getIds().isEmpty() ? super.listByIds(roleDelete.getIds()) : Collections.EMPTY_LIST);
        List<Integer> typeList = roleModelList.stream().map(obj -> obj.getType()).collect(Collectors.toList());

        if (CommonDict.ROLE_TYPE_INNER.equals(Objects.nonNull(roleModel) ? roleModel.getType() : CommonDict.ROLE_TYPE_DIY) || typeList.contains(CommonDict.ROLE_TYPE_INNER)) {
            throw new NoDeleteException("内置角色不可删除");
        }

    }

    /**
     * 内置角色不可修改
     *
     * @param roleDtoEdit
     */
    protected void updatedEnabled(RoleDtoEdit roleDtoEdit) throws DtoNullException {

        if (Objects.isNull(roleDtoEdit.getId()))
            throw new DtoNullException("参数为空");

        RoleModel roleModel = super.getById(roleDtoEdit.getId());

        if (CommonDict.ROLE_TYPE_INNER.equals(roleModel.getType()))
            throw new DtoNullException("内置角色不可修改");

    }

    protected List<MenuRoleDto> buildMenuRoleDto(Long roleId, List<Long> menuIds) throws DtoNullException {

        if (Objects.isNull(roleId) || Objects.isNull(menuIds) || menuIds.isEmpty()) {
            throw new DtoNullException("参数为空");
        }
        List<MenuRoleDto> dtoList = new ArrayList<>();
        MenuRoleDto dto = null;
        for (Long menuId : menuIds) {
            dto = new MenuRoleDto();
            dto.setRoleId(roleId);
            dto.setMenuId(menuId);
            dtoList.add(dto);
        }
        return dtoList;

    }

    protected List<MenuRoleDtoEdit> buildMenuRoleDtoEdit(Long roleId, List<Long> menuIds) throws DtoNullException {

        if (Objects.isNull(roleId) || Objects.isNull(menuIds) || menuIds.isEmpty()) {
            throw new DtoNullException("参数为空");
        }

        List<MenuRoleDtoEdit> dtoList = new ArrayList<>();
        MenuRoleDtoEdit dto = null;
        for (Long menuId : menuIds) {
            dto = new MenuRoleDtoEdit();
            dto.setRoleId(roleId);
            dto.setMenuId(menuId);
            dtoList.add(dto);
        }
        return dtoList;

    }

}
